home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.001 / crossfir~ / eutl / arglist / arglist.c next >
C/C++ Source or Header  |  1994-10-28  |  7KB  |  370 lines

  1. #include <arglist.h>
  2. #include <dynarray.h>
  3. #include <xmalloc.h>
  4. #include <libc.h>
  5.  
  6. char *arglist_packagever = "ArgList V1.0";
  7. char *arglist_Eoutofbounds = "Argument out of bounds";
  8. char *arglist_Etypemismatch = "Requested argument of wrong type";
  9. char *arglist_Eunpackerror = "Error while unpacking";
  10.  
  11. static ErrorFunction Erf = LongJmpErrorFunction;
  12.  
  13. enum ArgType { Long=0, String=1, Buffer=2, Char=3 };
  14.  
  15. static char *typetostring(int type)
  16. {
  17.   switch(type) {
  18.    case Long: return "Long";
  19.     break;
  20.    case String: return "String";
  21.     break;
  22.    case Buffer: return "Buffer";
  23.     break;
  24.    case Char: return "Char";
  25.     break;
  26.    default: return "Unknown Type\n";
  27.   }
  28. }
  29.  
  30. struct Arg {
  31.   enum ArgType type;
  32.   union {
  33.     char c;
  34.     long l;
  35.     unsigned long ul;
  36.     char *s;
  37.     struct {
  38.       void *b;
  39.       unsigned long size;
  40.     } b;
  41.   } u;
  42. };
  43.  
  44. struct __ArgList {
  45.   DynArray a;
  46.   int size;
  47. };
  48.  
  49. ArgList ArgList_create()
  50. {
  51.   ArgList ret;
  52.  
  53.   ret = xmalloc(sizeof(struct __ArgList));
  54.   ret->a = dyn_create(sizeof(struct Arg),0,10);
  55.   ret->size = 0;
  56.   return ret;
  57. }
  58.  
  59. void ArgList_destroy(ArgList gone)
  60. {
  61.   int i;
  62.   struct Arg *a;
  63.  
  64.   for(i=0;i<gone->size;i++) {
  65.     a = dyn_get(gone->a,i);
  66.     switch (a->type) {
  67.      case String: free(a->u.s);
  68.       break;
  69.      case Buffer: free(a->u.b.b);
  70.       break;
  71.      default:
  72.     }
  73.   }
  74.   dyn_destroy(gone->a);
  75.   free(gone);
  76. }
  77.  
  78. void ArgList_addLong(ArgList to,long val)
  79. {
  80.   struct Arg a;
  81.  
  82.   a.type = Long;
  83.   a.u.l = val;
  84.   dyn_set(to->a,to->size,&a);
  85.   to->size++;
  86. }
  87.  
  88. void ArgList_addChar(ArgList to,char val)
  89. {
  90.   struct Arg a;
  91.  
  92.   a.type = Char;
  93.   a.u.c = val;
  94.   dyn_set(to->a,to->size,&a);
  95.   to->size++;
  96. }
  97.  
  98. void ArgList_addString(ArgList to,char *val)
  99. {
  100.   struct Arg a;
  101.  
  102.   a.type = String;
  103.   a.u.s = xmalloc(strlen(val)+1);
  104.   strcpy(a.u.s,val);
  105.   dyn_set(to->a,to->size,&a);
  106.   to->size++;
  107. }
  108.  
  109. void ArgList_addBuf(ArgList to,void *buf,unsigned long len)
  110. {
  111.   struct Arg a;
  112.  
  113.   a.type = Buffer;
  114.   a.u.b.b = xmalloc(len);
  115.   bcopy(buf,a.u.b.b,len);
  116.   a.u.b.size = len;
  117.   dyn_set(to->a,to->size,&a);
  118.   to->size++;
  119. }
  120.  
  121. struct Arg *get(ArgList from,int posn)
  122. {
  123.   return (struct Arg *)dyn_get(from->a,posn);
  124. }
  125.  
  126. char ArgList_getChar(ArgList from,int posn)
  127. {
  128.   struct Arg *a;
  129.  
  130.   a = get(from,posn);
  131.   if (a->type != Char)
  132.     Erf(arglist_packagever,arglist_Etypemismatch,
  133.     "Type mismatch, expected char, got %s",typetostring(a->type));
  134.   return a->u.c;
  135. }
  136.  
  137. long ArgList_getLong(ArgList from,int posn)
  138. {
  139.   struct Arg *a;
  140.  
  141.   a = get(from,posn);
  142.   if (a->type != Long)
  143.     Erf(arglist_packagever,arglist_Etypemismatch,
  144.     "Type mismatch, expected long, got %s",typetostring(a->type));
  145.   return a->u.l;
  146. }
  147.  
  148. char *ArgList_getString(ArgList from,int posn)
  149. {
  150.   struct Arg *a;
  151.  
  152.   a = get(from,posn);
  153.   if (a->type != String)
  154.     Erf(arglist_packagever,arglist_Etypemismatch,
  155.     "Type mismatch, expected string, got %s",typetostring(a->type));
  156.   return a->u.s;
  157. }
  158.  
  159. void *ArgList_getBuf(ArgList from,int posn,unsigned long *len)
  160. {
  161.   struct Arg *a;
  162.  
  163.   a = get(from,posn);
  164.   if (a->type != Buffer)
  165.     Erf(arglist_packagever,arglist_Etypemismatch,
  166.     "Type mismatch, expected buffer, got %s",typetostring(a->type));
  167.   if (len!=NULL)
  168.     *len = a->u.b.size;
  169.   return a->u.b.b;
  170. }
  171.  
  172. int ArgList_getLength(ArgList from)
  173. {
  174.   return from->size;
  175. }
  176.  
  177. unsigned char *packlong(unsigned char *to,long v)
  178. {
  179.   if (sizeof(long)>4) {
  180.     int thirtyone = 31;
  181.     if (v < -((1<<thirtyone) - 1) || v > ((1<<thirtyone) - 1))
  182.       Erf(arglist_packagever,arglist_Eoutofbounds,
  183.       "Tried to send a long which is larger than 4 bytes.\n");
  184.   }
  185.   if (v<0) {
  186.     v = -v;
  187.     *to = (v >> 24);
  188.     *to |= 128;
  189.   } else {
  190.     *to = (v >> 24);
  191.   }
  192.   to++;
  193.   *to = (v >> 16) & 0xff;
  194.   to++;
  195.   *to = (v >> 8) & 0xff;
  196.   to++;
  197.   *to = v & 0xff;
  198.   to++;
  199.   return to;
  200. }
  201.  
  202. unsigned char *unpacklong(unsigned char *from,long *v)
  203. {
  204.   int lt0;
  205.   
  206.   lt0 = *from & 128;
  207.   *v = *from & 0x7f;
  208.   from++;
  209.   *v = (*v << 8) | *from;
  210.   from++;
  211.   *v = (*v << 8) | *from;
  212.   from++;
  213.   *v = (*v << 8) | *from;
  214.   from++;
  215.   if (lt0)
  216.     *v = - *v;
  217.   return from;
  218. }
  219.  
  220. unsigned char *packstring(unsigned char *to,char *s)
  221. {
  222.   long len = strlen(s);
  223.  
  224.   to = packlong(to,len);
  225.   bcopy(s,to,len);
  226.   return to+len;
  227. }
  228.  
  229. unsigned char *unpackstring(unsigned char *from,char **s)
  230. {
  231.   long len;
  232.  
  233.   from = unpacklong(from,&len);
  234.   *s = xmalloc(len+1);
  235.   bcopy(from,*s,len);
  236.   (*s)[len] = '\0';
  237.   return from+len;
  238. }
  239.  
  240. unsigned char *packbuffer(unsigned char *to,void *b,unsigned long size)
  241. {
  242.   to = packlong(to,size);
  243.   bcopy(b,to,size);
  244.   return to+size;
  245. }
  246.  
  247. unsigned char *unpackbuffer(unsigned char *from,void **b,unsigned long *size)
  248. {
  249.   from = unpacklong(from,size);
  250.   *b = xmalloc(*size);
  251.   bcopy(from,*b,*size);
  252.   return from + *size;
  253. }
  254.  
  255. void *ArgList_pack(ArgList from,unsigned long *osize)
  256. {
  257.   int i;
  258.   unsigned long size;
  259.   unsigned char *ret,*t;
  260.   struct Arg *a;
  261.  
  262.   size = 4; /* number of entries in argument list */
  263.   for(i=0;i<from->size;i++) {
  264.     a = dyn_get(from->a,i);
  265.     size++; /* type of what is being passed */
  266.     switch(a->type) {
  267.      case Long: size += 4;
  268.       break;
  269.      case String: size += strlen(a->u.s) + 4;
  270.       break;
  271.      case Buffer: size += a->u.b.size + 4;
  272.       break;
  273.      case Char: size += 1;
  274.       break;
  275.      default:
  276.       Erf(arglist_packagever,internal_Einternal,
  277.       "Bad type(%d) for arglist entry\n",a->type);
  278.     }
  279.   }
  280.   ret = xmalloc(size);
  281.   *osize = size;
  282.   t = packlong(ret,from->size);
  283.   for(i=0;i<from->size;i++) {
  284.     a = dyn_get(from->a,i);
  285.     *t = (char)(a->type);
  286.     t++;
  287.     switch(a->type) {
  288.      case Long: t = packlong(t,a->u.l);
  289.       break;
  290.      case String: t = packstring(t,a->u.s);
  291.       break;
  292.      case Buffer: t = packbuffer(t,a->u.b.b,a->u.b.size);
  293.       break;
  294.      case Char: *t = a->u.c;t++;
  295.       break;
  296.     }
  297.   }
  298.   return ret;
  299. }
  300.  
  301. ArgList ArgList_unpack(void *ifrom,unsigned long size)
  302. {
  303.   unsigned char *from = ifrom;
  304.   unsigned char *end = from + size;
  305.   int type;
  306.   long nents,i;
  307.   ArgList ret;
  308.   struct Arg a;
  309.  
  310.   from = unpacklong(from,&nents);
  311.  
  312.   if (nents>size) 
  313.     Erf(arglist_packagever,arglist_Eunpackerror,
  314.     "Can't possibly have more entries(%d) than the size(%d)\n",
  315.     nents,size);
  316.   ret = xmalloc(sizeof(struct __ArgList));
  317.   ret->a = dyn_create(sizeof(struct Arg),nents,10);
  318.   ret->size = nents;
  319.   for(i=0;i<nents;i++) {
  320.     type = *from;
  321.     from++;
  322.     switch(type) {
  323.      case Long:
  324.       from = unpacklong(from,&a.u.l);
  325.       break;
  326.      case String:
  327.       from = unpackstring(from,&a.u.s);
  328.       break;
  329.      case Buffer:
  330.       from = unpackbuffer(from,&a.u.b.b,&a.u.b.size);
  331.       break;
  332.      case Char:
  333.       a.u.c = *from;from++;
  334.       break;
  335.      default:
  336.       Erf(arglist_packagever,arglist_Eunpackerror,
  337.       "Invalid type(%d) while unpacking\n",type);
  338.     }
  339.     if (from>end) {
  340.       Erf(arglist_packagever,arglist_Eunpackerror,
  341.       "More stuff specified in arglist than space given by size\n");
  342.     }
  343.     a.type = type;
  344.     dyn_set(ret->a,i,&a);
  345.   }
  346.   return ret;
  347. }
  348.  
  349. void ArgList_send(TcpSocket to,ArgList val)
  350. {
  351.   void *buf;
  352.   unsigned long size;
  353.  
  354.   buf = ArgList_pack(val,&size);
  355.   SendSizedMsg(to,buf,size);
  356.   free(buf);
  357. }
  358.  
  359. ArgList ArgList_receive(TcpSocket from)
  360. {
  361.   ArgList ret;
  362.   void *buf;
  363.   long size;
  364.   buf = GetSizedMsg(from,&size);
  365.   ret = ArgList_unpack(buf,size);
  366.   return ret;
  367. }
  368.  
  369.  
  370.